package com.xhwl.logistics.strategy.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xhwl.common.dto.cent.vehicle.SupplierConfigDTO;
import com.xhwl.common.enums.CategoryEnum;
import com.xhwl.common.enums.OrganizationTypeEnum;
import com.xhwl.common.enums.vehicle.ParkSupplierEnum;
import com.xhwl.common.enums.vehicle.SyncTypeEnum;
import com.xhwl.common.exception.BusinessException;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.pojo.cent.device.DeviceProjSupplierCategory;
import com.xhwl.common.pojo.cent.sdata.Account;
import com.xhwl.common.pojo.cent.sdata.Organization;
import com.xhwl.common.pojo.cent.vehicle.VehcArea;
import com.xhwl.common.pojo.cent.vehicle.VehcPassage;
import com.xhwl.common.query.cent.device.ProductAccessQuery;
import com.xhwl.common.query.cent.sdata.OrganizationQuery;
import com.xhwl.common.vo.cent.vehicle.SyncVO;
import com.xhwl.logistics.dao.VehcAreaDao;
import com.xhwl.logistics.dao.VehcPassageDao;
import com.xhwl.logistics.service.IVehcPassageService;
import com.xhwl.logistics.service.cent.IOrganizationService;
import com.xhwl.logistics.service.cent.IProductAccessCentService;
import com.xhwl.logistics.strategy.BasicInfoSyncStrategy;
import com.xhwl.logistics.strategy.InfoSyncSupplierStrategy;
import com.xhwl.logistics.strategy.context.InfoSyncSupplierStrategyContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description: 基础信息通道同步实现类
 * @author: lu.Aaron
 * @create: 2021-06-30 09:35
 **/
@Slf4j
//@Component
public class BasicInfoPassageSyncServiceImpl implements BasicInfoSyncStrategy {
    @Autowired
    private InfoSyncSupplierStrategyContext infoSyncSupplierStrategyContext;

    @Autowired
    private IProductAccessCentService productAccessCentService;

    @Autowired
    private VehcPassageDao vehcPassageDao;

    @Autowired
    private IVehcPassageService vehcPassageService;

    @Autowired
    private IOrganizationService organizationService;

    @Autowired
    private VehcAreaDao vehcAreaDao;
    @Override
    public int getSyncType() {
        return SyncTypeEnum.PASSAGE.type;
    }

    @Override
    public ResultJson basicInfoSync(Short industryId, SyncVO syncVO) {
        log.info("同步车场通道开始(sync parking passage start)");

        //先根据项目id和产品分类id查询供应商
        @NotNull Integer projectId = syncVO.getProjectId();
        @NotNull String parkId = syncVO.getParkId();
        List<DeviceProjSupplierCategory> deviceProjSupplierCategories = productAccessCentService.listProductAccess(industryId, new ProductAccessQuery(projectId, CategoryEnum.YARD_GATE.getId()));
        if (deviceProjSupplierCategories.isEmpty()) {
            throw new BusinessException("该项目未配置供应商，请先配置");
        }
        DeviceProjSupplierCategory productAccess = deviceProjSupplierCategories.get(0);
        JSONObject properties = productAccess.getProperties();
        //获取供应商配置信息
        SupplierConfigDTO supplierConfigDTO = JSON.toJavaObject(properties, SupplierConfigDTO.class);
        //根据supplierId以及策略模式选取对应的接口实现类
         Integer supplierId = productAccess.getSupplierId();
         InfoSyncSupplierStrategy infoSyncSupplierService = infoSyncSupplierStrategyContext.getInfoSyncSupplierService(ParkSupplierEnum.getParkSupplierEnum(supplierId));
         //PassageDTO passageDTO = new PassageDTO();
        // passageDTO.setParkId(parkId);
         Map<String, Object> map = new HashMap<>();
         map.put("parkId",parkId);
         List<VehcPassage> listFromSupplier = infoSyncSupplierService.getPassageList(map,supplierConfigDTO);


        if (listFromSupplier.isEmpty()) {
            throw new BusinessException("查询供应商，无相关通道信息");
        }
        //判断查询到通道是否已经在数据库了，在就不新增，不在就新增
        List<String> thirdPassageIds = listFromSupplier.stream().map(p -> p.getThirdPassageId()).collect(Collectors.toList());
        List<VehcPassage> listFromDB = vehcPassageDao.selectList(new QueryWrapper<VehcPassage>().in("third_passage_id", thirdPassageIds).eq("project_id",projectId));
        if (listFromDB.isEmpty()) {
            //直接新增
            syncPassageToOrg(industryId, projectId, listFromSupplier);
            vehcPassageService.saveBatch(listFromSupplier);
        }else{

            //判断listFromDB与listFromSupplier关系，是则要找出补集，差集，再新增或删除
            List<String> thirdPassageIdFromDB = listFromDB.stream().map(l -> l.getThirdPassageId()).collect(Collectors.toList());
            List<String> thirdPassageIdFromSupplier = listFromSupplier.stream().map(l -> l.getThirdPassageId()).collect(Collectors.toList());
            //需要删除的情况
            List<Integer> deleteList = new ArrayList<>();
            List<Integer> deleteOrgIdList = new ArrayList<>();
            listFromDB.forEach(l->{
                if (!thirdPassageIdFromSupplier.contains(l.getThirdPassageId())) {
                    //说明数据需要删除该数据
                    deleteList.add(l.getId());
                    deleteOrgIdList.add(l.getOrgId());
                }
            });
            if (!deleteList.isEmpty()) {
                vehcPassageService.removeByIds(deleteList);
                organizationService.batchDelete(deleteOrgIdList);
            }
            //需要新增的情况
            List<VehcPassage> insertList = new ArrayList<>();

            listFromSupplier.forEach(l->{
                if (!thirdPassageIdFromDB.contains(l.getThirdPassageId())) {
                    insertList.add(l);
                }
            });
            syncPassageToOrg(industryId, projectId, insertList);
            vehcPassageService.saveBatch(insertList);

        }

        log.info("同步车场通道结束(sync parking passage end)");
        return ResultJson.success("同步通道成功");

    }

    private void syncPassageToOrg(Short industryId, Integer projectId, List<VehcPassage> insertList) {
        //根据车场主键id获取对应的orgId
        List<Integer> ids = insertList.stream().map(p -> p.getAreaId()).collect(Collectors.toList());
        List<VehcArea> vehcAreas = vehcAreaDao.selectBatchIds(ids);
        //根据projectId查询对应的organization信息
        OrganizationQuery organizationQuery = new OrganizationQuery();
        List<Integer> list = new ArrayList<>();
        list.add(projectId);
        organizationQuery.setProjectIds(list);
        organizationQuery.setIndustryId(industryId);
        List<OrganizationTypeEnum> organizationTypeEnums = new ArrayList<>();
        organizationTypeEnums.add(OrganizationTypeEnum.PROJECT);

        //cent-common修改OrganizationQuery withTypes方法已修改
        organizationQuery.withTypes(organizationTypeEnums.stream().map(organizationTypeEnum -> organizationTypeEnum.getId().intValue()).collect(Collectors.toList()));

        List<Organization> listFromCentDataCore = organizationService.list(organizationQuery);
        Organization organizationFrom = listFromCentDataCore.get(0);
        Integer enterpriseId = organizationFrom.getEnterpriseId();
        Integer level = organizationFrom.getLevel();
        List<Organization> organizations = new ArrayList<>();
        insertList.forEach(p->{
            Organization organization = new Organization();
            organization.setEnterpriseId(enterpriseId);
            organization.setIndustryId(industryId);

            organization.setParentId(p.getAreaOrgId());

            organization.setLevel(level+3);

            //cent-common修改Organization setType方法已修改
            organization.setType(OrganizationTypeEnum.PASSAGE.getId().intValue());

            organization.setName(p.getName());
            organizations.add(organization);
        });
        ResultJson resultJson = organizationService.create(organizations, new Account());
        Object result = resultJson.getResult();
        List<Organization> OrganizationList = JSON.parseArray(JSON.toJSONString(result), Organization.class);
        //处理insertList，将每一条数据对应的orgId更新到处理insertList
        insertList.forEach(p->{
            OrganizationList.forEach(o->{
                if (p.getName().equals(o.getName())) {
                    p.setOrgId(o.getId());
                }
                p.setProjectId(projectId);
            });
        });
    }


}

